package com.jic.manager.impl;

import java.lang.Long;
import java.util.*;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jic.common.base.vo.AdminOperate;
import com.jic.common.base.vo.RestResult;
import com.jic.enums.RedisKey;
import com.jic.manager.common.util.BeanUtil;
import com.jic.manager.entity.*;
import com.jic.manager.enums.RoleTypeEnum;
import com.jic.manager.mapper.*;
import com.jic.manager.request.SysRoleMenuRequest;
import com.jic.manager.request.SysRoleMenuVerifyRequest;
import com.jic.manager.request.SysRoleRequest;
import com.jic.manager.request.orgcenter.SysDeptTreeRequest;
import com.jic.manager.response.SysMenuResponse;
import com.jic.manager.response.SysRoleInfoMenuResponse;
import com.jic.manager.response.SysRoleMenuResponse;
import com.jic.manager.response.SysRoleResponse;
import com.jic.manager.service.SysRoleService;
import com.jic.common.base.vo.Page;
import com.jic.common.base.vo.PageResult;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 角色信息表
 * @author : 
 * @email : 
 * @since : 2020-02-26 09:39:06
 * @version : v1.0.0
 */
@Service
public class SysRoleServiceImpl implements SysRoleService{

    @Resource
    private SysRoleMapper sysRoleMapper;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private SysRoleMenuMapper sysRoleMenuMapper;

    @Resource
    private SysRoleLogMapper sysRoleLogMapper;

    @Resource
    private SysMenuMapper sysMenuMapper;

    @Resource
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private SysRoleMenuVerifyMapper sysRoleMenuVerifyMapper;



    @Override
    public long insert(SysRole sysRole) {
        long flag = sysRoleMapper.insert(sysRole);
        return flag;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean delete(SysRoleRequest sysRoleRequest) {
        AdminOperate adminOperate = sysRoleRequest.getAdminOperate();
        Long id = sysRoleRequest.getId();
        SysUser sysUser = new SysUser();
        sysUser.setRoleid(id);
        List<SysUser> list = sysUserMapper.query(sysUser);
        if(list.size()>0){
            return false;
        }
        sysRoleMapper.delete(id);
        SysRoleMenuVerify sysRoleMenuVerify = new SysRoleMenuVerify();
        sysRoleMenuVerify.setRoleid(id);
        sysRoleMenuVerify.setRoleName(sysRoleRequest.getRoleName());
        sysRoleMenuVerify.setOperateType("3");
        sysRoleMenuVerify.setStatus("2");
        sysRoleMenuVerify.setCreatorName(adminOperate.getOperateName());
        sysRoleMenuVerify.setCreator(adminOperate.getOperator());
        sysRoleMenuVerify.setDeptId(adminOperate.getDeptId());
        sysRoleMenuVerifyMapper.insert(sysRoleMenuVerify);
        return true;
    }

    @Override
    public void deleteByIds(SysRoleRequest sysRoleRequest) {
        String ids = sysRoleRequest.getIds();
        String[] idList = ids.split(",");
        for (String id : idList) {
            sysRoleMapper.delete(Long.valueOf(id));
        }
    }

    @Override
    public long update(SysRole sysRole) {
        return sysRoleMapper.update(sysRole);
    }

    @Override
    public SysRole queryByPrimaryKey(Long id){
        return sysRoleMapper.queryByPrimaryKey(id);
    }

    @Override
    public List<SysRole> query(SysRole sysRole){
        List<Long> deptIds = sysRole.getAdminOperate().getDeptIds();
        return sysRoleMapper.queryByDeptIds(StringUtils.join(deptIds,","));
    }

    @Override
    public PageResult<SysRole> queryPage(SysRole sysRole, Page pageQuery) {
        //计算下标
        int startIndex = (pageQuery.getStart() - 1) * pageQuery.getLimit();
        List<SysRole> list = sysRoleMapper.queryPage(startIndex, pageQuery.getLimit(), sysRole);
        long count = sysRoleMapper.queryPageCount(sysRole);
        PageResult pageResult = new PageResult();
        pageResult.setRows(list);
        pageResult.setTotal(count);
        return pageResult;
    }

    /**
     * 查询角色 根据当前用户所属组织层级 查出当前及所有下属层级角色
     * @param sysRoleVo
     * @return
     */
    @Override
    public RestResult<PageResult<SysRole>> queryPageList(SysRoleRequest sysRoleVo) {
        RestResult<PageResult<SysRole>> pageResultRestResult = new RestResult<>();

        SysRole sysRole = new SysRole();
        BeanUtils.copyProperties(sysRoleVo,sysRole);
        AdminOperate adminOperate = sysRoleVo.getAdminOperate();
        sysRole.setDeleteFlag(0);
        if (sysRoleVo.getStart() != null && sysRoleVo.getStart() != 0 && sysRoleVo.getLimit() != null){

            //分页
//            sysRole.setDeptId(String.valueOf(adminOperate.getDeptId()));
            PageResult<SysRole> sysRolePageResult = queryPage(sysRole, new Page() {{
                setStart(sysRoleVo.getStart());
                setLimit(sysRoleVo.getLimit());
            }});
            pageResultRestResult.setCode("0000");
            pageResultRestResult.setData(sysRolePageResult);
        }else{
            List<SysRole> sysRoles = sysRoleMapper.query(sysRole);
            pageResultRestResult.setCode("0000");
            pageResultRestResult.setData(new PageResult<SysRole>(){{
                setRows(sysRoles);
            }});
        }
        return pageResultRestResult;
    }

    /**
     * 卡奥斯新增角色及菜单权限
     * @param sysRoleRequest
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public long saveSysRole(SysRoleRequest sysRoleRequest) {
        AdminOperate adminOperate = sysRoleRequest.getAdminOperate();
        SysRole sysRole = BeanUtil.copy(sysRoleRequest,SysRole.class);
        if(sysRoleRequest.getId() == null || sysRoleRequest.getId() == 0){
            //新增
            sysRoleMapper.insert(sysRole);
        } else{
            sysRoleMapper.update(sysRole);
        }
        List<SysRoleMenuRequest> roleMenus = sysRoleRequest.getRoleMenusList();
        Long roleId = sysRole.getId();
        sysRoleMenuMapper.deleteByRoleId(roleId);
        for(SysRoleMenuRequest menus : roleMenus){
            menus.setRoleid(sysRole.getId());
        }
        //新增
        sysRoleMenuMapper.insertList(roleMenus);
        //新增日志
        sysRoleLogMapper.insert(new SysRoleLog(){{
            setRoleId(roleId);
            setContent(JSONArray.toJSONString(roleMenus));
            setCreator(adminOperate.getOperator());
            setCreatorName(adminOperate.getOperateName());
            setCreateTime(new Date());
        }});
        return 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysRoleInfoMenuResponse getSysRoleInfo(SysRoleRequest sysRoleRequest) {
        SysRoleInfoMenuResponse sysRoleInfoMenuResponse = new SysRoleInfoMenuResponse();
        if(sysRoleRequest.getId() != null){
            SysRole sysRole = sysRoleMapper.queryByPrimaryKey(sysRoleRequest.getId());
            SysRoleResponse sysRoleResponse = new SysRoleResponse();
            BeanUtils.copyProperties(sysRole,sysRoleResponse);
            sysRoleInfoMenuResponse.setSysRoleResponse(sysRoleResponse);
        }
        //查询所有菜单
        List<SysMenu> sysMenus = new ArrayList<>();
        SysRoleMenu parm = new SysRoleMenu();
        String type = sysRoleRequest.getType();
        sysMenus = sysMenuMapper.query(new SysMenu() {{
            setOwningPlatform(type);
            setDeleteFlag(0);
        }});
        List<SysMenuResponse> resultList = new ArrayList<>();
        for (SysMenu menu : sysMenus) {
            if(menu == null){
                continue;
            }
            SysMenuResponse sysMenuResponse = new SysMenuResponse();
            BeanUtils.copyProperties(menu,sysMenuResponse);
            if (StringUtils.isEmpty(sysMenuResponse.getPid()) || sysMenuResponse.getPid().equals("0")) {
                sysMenuResponse.setLevel(0);
                if (!exists(resultList, menu) && menu.getDeleteFlag().equals(0)) {
                    resultList.add(sysMenuResponse);
                }
            }
        };
        findChildren(resultList, sysMenus,1);
        resultList.sort((o1, o2) -> o1.getSort().compareTo(o2.getSort()));
        sysRoleInfoMenuResponse.setMenuList(resultList);
        return sysRoleInfoMenuResponse;
    }

    /**
     * 角色提交审核
     * @param sysRole
     * @return
     */
    @Override
    public Boolean submitReview(SysRole sysRole) {
        sysRole.setStatus(2L);
        sysRole.setUpdater(sysRole.getAdminOperate().getOperator());
        sysRole.setUpdaterName(sysRole.getAdminOperate().getOperateName());
        sysRoleMapper.updateStatus(sysRole);
        return true;
    }

    /**
     * 批量提交审核
     * @param sysRoleRequest
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean batchSubmitReview(SysRoleRequest sysRoleRequest) {
        sysRoleRequest.setStatus(2L);
        sysRoleRequest.setUpdater(sysRoleRequest.getAdminOperate().getOperator());
        sysRoleRequest.setUpdaterName(sysRoleRequest.getAdminOperate().getOperateName());
        sysRoleMapper.batchUpdateList(sysRoleRequest);
        return true;
    }

    /**
     * 审核角色 变更角色菜单关联关系 或新增
     * @param sysRole
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean roleReview(SysRole sysRole) {

        AdminOperate adminOperate = sysRole.getAdminOperate();
        SysRoleMenuVerify sysRoleMenuVerify = sysRoleMenuVerifyMapper.getSysRoleMenuVerifyByRoleId(sysRole.getId());
        //审核不通过
        if(4 == sysRole.getStatus()){
            sysRole.setUpdater(sysRole.getAdminOperate().getOperator());
            sysRole.setUpdaterName(sysRole.getAdminOperate().getOperateName());
            sysRoleMapper.updateStatus(sysRole);
            sysRoleMenuVerify.setStatus("3");

        }else{
            //审核通过
            JSONObject map = JSONObject.parseObject(sysRoleMenuVerify.getModifyText());
            if(RoleTypeEnum.ADD_TYPE.getType().equals(sysRoleMenuVerify.getOperateType())){
                List<SysRoleMenuRequest> roleMenusList = JSONObject.parseArray(map.get("roleMenusList").toString(), SysRoleMenuRequest.class);
                SysRole role = new SysRole();
                role.setType(map.getString("type"));
                role.setId(sysRole.getId());
                role.setUpdater(adminOperate.getOperator());
                role.setUpdaterName(adminOperate.getOperateName());
                role.setStatus(sysRole.getStatus());
                sysRoleMapper.update(role);
                for(SysRoleMenuRequest menus : roleMenusList){
                    menus.setRoleid(sysRole.getId());
                }
                //数据变更
                insertMenuOrLog(sysRole, roleMenusList, adminOperate, map);
            }else if(RoleTypeEnum.EDIT_TYPE.getType().equals(sysRoleMenuVerify.getOperateType())){
                List<SysRoleMenuRequest> roleMenusList = JSONObject.parseArray(map.get("roleMenusList").toString(), SysRoleMenuRequest.class);
                SysRole role = new SysRole();
                role.setType(map.getString("type"));
                role.setId(sysRole.getId());
                role.setUpdater(adminOperate.getOperator());
                role.setUpdaterName(adminOperate.getOperateName());
                role.setStatus(sysRole.getStatus());
                sysRoleMapper.update(role);
                sysRoleMenuMapper.deleteByRoleId(sysRole.getId());
                //数据变更
                insertMenuOrLog(sysRole, roleMenusList, adminOperate, map);
            }else if(RoleTypeEnum.DELETE_TYPE.getType().equals(sysRoleMenuVerify.getOperateType())){
                sysRoleMapper.delete(sysRole.getId());
                sysRoleMenuMapper.deleteByRoleId(sysRole.getId());
            }
            sysRoleMenuVerify.setStatus("2");
        }
        sysRoleMenuVerify.setRemark(sysRole.getRemark());
        sysRoleMenuVerify.setUpdater(adminOperate.getOperator());
        sysRoleMenuVerify.setUpdaterName(adminOperate.getOperateName());
        sysRoleMenuVerifyMapper.update(sysRoleMenuVerify);
        return true;
    }

    /**
     * 批量审核角色
     * @param sysRoleRequest
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean batchRoleReview(SysRoleRequest sysRoleRequest) {
        AdminOperate adminOperate = sysRoleRequest.getAdminOperate();
        for(int i=0; i< sysRoleRequest.getRoleRequestList().size(); i++){
            Long roleId = sysRoleRequest.getRoleRequestList().get(i).getId();
            SysRoleMenuVerify sysRoleMenuVerify = sysRoleMenuVerifyMapper.getSysRoleMenuVerifyByRoleId(roleId);
            //审核不通过
            if(4 == sysRoleRequest.getStatus()){
                SysRole sysRole = new SysRole();
                sysRole.setId(roleId);
                sysRole.setStatus(sysRoleRequest.getStatus());
                sysRole.setRemark(sysRoleRequest.getRemark());
                sysRole.setUpdater(adminOperate.getOperator());
                sysRole.setUpdaterName(adminOperate.getOperateName());
                sysRoleMapper.updateStatus(sysRole);
                sysRoleMenuVerify.setStatus("3");

            }else{
                //审核通过
                JSONObject map = JSONObject.parseObject(sysRoleMenuVerify.getModifyText());
                if(RoleTypeEnum.ADD_TYPE.getType().equals(sysRoleMenuVerify.getOperateType())){
                    List<SysRoleMenuRequest> roleMenusList = JSONObject.parseArray(map.get("roleMenusList").toString(), SysRoleMenuRequest.class);
                    SysRole role = new SysRole();
                    role.setType(map.getString("type"));
                    role.setId(roleId);
                    role.setStatus(sysRoleRequest.getStatus());
                    role.setRemark(sysRoleRequest.getRemark());
                    role.setUpdater(adminOperate.getOperator());
                    role.setUpdaterName(adminOperate.getOperateName());
                    sysRoleMapper.update(role);
                    for(SysRoleMenuRequest menus : roleMenusList){
                        menus.setRoleid(roleId);
                    }
                    //数据变更
                    insertMenuOrLog(new SysRole(){{setId(roleId);}}, roleMenusList, adminOperate, map);
                }else if(RoleTypeEnum.EDIT_TYPE.getType().equals(sysRoleMenuVerify.getOperateType())){
                    List<SysRoleMenuRequest> roleMenusList = JSONObject.parseArray(map.get("roleMenusList").toString(), SysRoleMenuRequest.class);
                    SysRole role = new SysRole();
                    role.setType(map.getString("type"));
                    role.setId(roleId);
                    role.setUpdater(adminOperate.getOperator());
                    role.setUpdaterName(adminOperate.getOperateName());
                    sysRoleMapper.update(role);
                    sysRoleMenuMapper.deleteByRoleId(roleId);
                    //数据变更
                    insertMenuOrLog(new SysRole(){{setId(roleId);}}, roleMenusList, adminOperate, map);
                }else if(RoleTypeEnum.DELETE_TYPE.getType().equals(sysRoleMenuVerify.getOperateType())){
                    sysRoleMapper.delete(roleId);
                    sysRoleMenuMapper.deleteByRoleId(roleId);
                }
                sysRoleMenuVerify.setStatus("2");
            }
            sysRoleMenuVerify.setRemark(sysRoleRequest.getRemark());
            sysRoleMenuVerify.setUpdater(adminOperate.getOperator());
            sysRoleMenuVerify.setUpdaterName(adminOperate.getOperateName());
            sysRoleMenuVerifyMapper.update(sysRoleMenuVerify);
        }

        return true;
    }

    /**
     * 数据变更
     * @param sysRole
     * @param roleMenusList
     * @param adminOperate
     * @param map
     */
    private  void insertMenuOrLog(SysRole sysRole,List<SysRoleMenuRequest> roleMenusList,  AdminOperate adminOperate, JSONObject map){

        for(SysRoleMenuRequest menus : roleMenusList){
            menus.setRoleid(sysRole.getId());
        }
        sysRoleMenuMapper.insertList(roleMenusList);
        sysRoleLogMapper.insert(new SysRoleLog(){{
            setRoleId(sysRole.getId());
            setContent(map.get("roleMenusList").toString());
            setCreator(adminOperate.getOperator());
            setCreatorName(adminOperate.getOperateName());
            setCreateTime(new Date());
        }});
    }

    /**
     * 撤销审核
     * @param sysRole
     * @return
     */
    @Override
    public Boolean revokeReview(SysRole sysRole) {
        SysRole role = sysRoleMapper.queryByPrimaryKey(sysRole.getId());
        if(role.getStatus() != 2){
            throw new RuntimeException("状态异常，无法撤销提交");
        }
        sysRole.setStatus(1L);
        sysRole.setUpdater(sysRole.getAdminOperate().getOperator());
        sysRole.setUpdaterName(sysRole.getAdminOperate().getOperateName());
        sysRoleMapper.updateStatus(sysRole);
        return null;
    }


    /**
     * 判断当前权限是否添加过
     *
     * @param sysMenus
     * @param sysMenu
     * @return
     */
    private boolean exists(List<SysMenuResponse> sysMenus, SysMenu sysMenu) {
        boolean exist = false;
        for (SysMenuResponse menu : sysMenus) {
            if (menu.getId() == sysMenu.getId()) {
                exist = true;
            }
        }
        return exist;
    }

    private void findChildren(List<SysMenuResponse> SysMenus, List<SysMenu> menus, int type) {
        for (SysMenuResponse SysMenu : SysMenus) {
            List<SysMenuResponse> children = new ArrayList<>();
            for (SysMenu menu : menus) {
                if (menu == null){
                    continue;
                }
                if ("2".equals(menu.getTypes()) && type == 1) {
                    // 如果是获取类型不需要按钮，且菜单类型是按钮的，直接过滤掉
                    continue;
                }
                if (SysMenu.getId() != null && String.valueOf(SysMenu.getId()).equals(menu.getPid())) {
//                    SysMenuVo sysMenuVo = (SysMenuVo) StrongParentSubclass.parentSubclass(menu, new SysMenuVo());
                    SysMenuResponse sysMenuResponse = new SysMenuResponse();
                    BeanUtils.copyProperties(menu,sysMenuResponse);
                    sysMenuResponse.setParentName(SysMenu.getName());
                    sysMenuResponse.setLevel(SysMenu.getLevel()+1);
                    if (!exists(children, menu)) {
                        children.add(sysMenuResponse);
                    }
                }
            }
            SysMenu.setChildren(children);
            children.sort((o1, o2) -> o1.getSort().compareTo(o2.getSort()));
            findChildren(children, menus,type);
        }
    }
}